package com.dashu.core.service;

import com.dashu.base.enums.ReplRyCode;
import com.dashu.base.enums.common.GenderType;
import com.dashu.core.model.Relationship;
import com.dashu.core.result.PageEnty;
import com.dashu.base.utils.CopyUtil;
import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.core.dto.company.CompanyParentDTO;
import com.dashu.core.dto.company.CompanyParentListDTO;
import com.dashu.core.dto.company.BindRelationshipDTO;
import com.dashu.core.handler.VerificationException;
import com.dashu.core.model.CompanyParent;
import com.dashu.core.model.CompanyPersonal;
import com.dashu.core.model.QCompanyParent;
import com.dashu.core.result.ResultBean;
import com.dashu.core.vo.company.CompanyParentListVO;
import com.dashu.core.vo.company.CompanyParentVO;
import com.dashu.core.vo.UpdateEntityVO;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;


@Slf4j
@Service
public class CompanyParentService extends DataService {
    @Autowired
    private RelationshipService relationshipService;
    @Autowired
    private CompanyPersonalService companyPersonalService;

    @Transactional
    public CompanyParentDTO add(CompanyParentVO companyParentVO) {
        CompanyParent companyParent = CopyUtil.copyEnty(companyParentVO, CompanyParent.class);
        try {
            long userId = Long.parseLong(VerificationUtil.getUserId());
            companyParent.setId(UIDUtil.nextId());
            companyParent.setCreateUser(userId);
            companyParent.setCreateTime(System.currentTimeMillis());
            entityManager.persist(companyParent);
//            entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
        } catch (Exception e) {
            e.printStackTrace();
            throw new VerificationException(ReplRyCode.DATA_NOT_INVALID, ReplRyCode.DATA_NOT_INVALID.getMessage());
        }
        CompanyParentDTO companyParentDTO = CopyUtil.copyEnty(companyParent, CompanyParentDTO.class);
        return companyParentDTO;

    }

    @Transactional
    public boolean deleteByCompanyParentId(long companyParentId) {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyParent.id.eq(companyParentId));
        List<Relationship> relationships = relationshipService.relationshipsList(companyParentId, 0);
        relationships.stream().forEach(rs -> {
            relationshipService.deleteByRelationshipId(rs.getId());
        });
        CompanyParent companyParent;
        queryFactory.select();
        companyParent = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue()).fetchOne();
        if (companyParent == null)
            throw new VerificationException(ReplRyCode.COMPANY_PARENT_NOT_DATA, ReplRyCode.COMPANY_PARENT_NOT_DATA.getMessage());
        entityManager.remove(companyParent);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return true;

    }


    public void deleteCompany(long companyId) throws Exception {
        List<CompanyParent> companyParents = findByCompanyId(companyId);
        companyParents.stream().forEach(cp -> {
            cp.setCompanyId(0);
            entityManager.merge(cp);
//        entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
        });


    }


    public List<CompanyParent> findByCompanyId(long companyId) throws Exception {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyParent.companyId.eq(companyId));
        List<CompanyParent> companyParents = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue())
                .fetch();
        return companyParents;

    }

    @Transactional
    public CompanyParentDTO updataByCompanyParentId(UpdateEntityVO<CompanyParentVO> updateCompanyParentVO) throws Exception {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        CompanyParentVO companyParentVO = updateCompanyParentVO.getEntityVO();
        CompanyParentDTO companyParentDTO = existByParent(companyParentVO.getParentPhone(), companyParentVO.getCompanyId());
        if (companyParentDTO != null) {
            throw new VerificationException(ReplRyCode.EXIST_PHONE, ReplRyCode.EXIST_PHONE.getMessage());
        }
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyParent.id.eq(updateCompanyParentVO.getId()));
        CompanyParent companyParent;
        try {
            companyParent = queryFactory
                    .select(qCompanyParent)
                    .from(qCompanyParent)
                    .where(booleanBuilder.getValue()).fetchOne();
            if (companyParent == null)
                throw new VerificationException(ReplRyCode.COMPANY_PARENT_NOT_DATA, ReplRyCode.COMPANY_PARENT_NOT_DATA.getMessage());
            companyParent.setUpdateUser(userId);
            companyParent.setUpdateTime(new Date().getTime());
            if (companyParentVO.getCompanyId() != 0)
                companyParent.setCompanyId(companyParentVO.getCompanyId());
            if (companyParentVO.getParentName() != null)
                companyParent.setParentName(companyParentVO.getParentName());
            if (companyParentVO.getParentPhone() != 0)
                companyParent.setParentPhone(companyParentVO.getParentPhone());
            if (companyParentVO.getIcon() != null)
                companyParent.setIcon(companyParentVO.getIcon());
            if (companyParentVO.getGender() != null)
                companyParent.setGender(GenderType.map.get(companyParentVO.getGender()));
            companyParent = entityManager.merge(companyParent);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
//        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        CompanyParentDTO CompanyParentDTO = CopyUtil.copyEnty(companyParent, CompanyParentDTO.class);
        return CompanyParentDTO;

    }

    public List<CompanyParentDTO> findByCreteUser(PageEnty<Long> baseVo) throws Exception {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long baseId = baseVo.getBaseId() == 0 ? userId : baseVo.getBaseId();
        booleanBuilder.and(qCompanyParent.createUser.eq(baseId));
        List<CompanyParent> companyParents = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue())
                .fetch();
        List<CompanyParentDTO> recycleDTOS = CopyUtil.copyList(companyParents, CompanyParentDTO.class);
        return recycleDTOS;

    }

    public CompanyParentDTO findByCompanyParentId(long companyParentId) {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyParent.id.eq(companyParentId));
        CompanyParent companyParent = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue()).fetchOne();
        if (companyParent == null)
            throw new VerificationException(ReplRyCode.COMPANY_PARENT_NOT_DATA, ReplRyCode.COMPANY_PARENT_NOT_DATA.getMessage());
        CompanyParentDTO CompanyParentDTO = CopyUtil.copyEnty(companyParent, CompanyParentDTO.class);
        return CompanyParentDTO;

    }

    public CompanyParentDTO existByParent(long parentPhonee, long companyId) {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyParent.parentPhone.eq(parentPhonee));
        booleanBuilder.and(qCompanyParent.companyId.eq(companyId));
        CompanyParent companyParent = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue()).fetchOne();
        CompanyParentDTO CompanyParentDTO = CopyUtil.copyEnty(companyParent, CompanyParentDTO.class);
        return CompanyParentDTO;

    }

    public long parentCount(PageEnty<CompanyParentListVO> companyParentListVO) throws Exception {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        List<CompanyParentListDTO> companyParentListDTOS = Lists.newArrayList();
        CompanyParentListVO parentListVO = companyParentListVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (!StringUtils.isEmpty(parentListVO.getParentName())) {
            booleanBuilder.and(qCompanyParent.parentName.eq(parentListVO.getParentName()));
        } else if (!StringUtils.isEmpty(parentListVO.getGender())) {
            booleanBuilder.and(qCompanyParent.gender.eq(GenderType.map.get(parentListVO.getGender())));
        }
        long baseId = companyParentListVO.getBaseId() == 0 ? userId : companyParentListVO.getBaseId();
        if (admin != baseId)
            booleanBuilder.and(qCompanyParent.createUser.eq(baseId));
        long count = queryFactory
                .select(qCompanyParent.count())
                .from(qCompanyParent)
                .where(booleanBuilder.getValue())
                .fetchCount();
        return count;
    }


    public List<CompanyParentListDTO> pageParentList(PageEnty<CompanyParentListVO> companyParentListVO) throws Exception {
        QCompanyParent qCompanyParent = QCompanyParent.companyParent;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        List<CompanyParentListDTO> companyParentListDTOS = Lists.newArrayList();
        CompanyParentListVO parentListVO = companyParentListVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (!StringUtils.isEmpty(parentListVO.getParentName())) {
            booleanBuilder.and(qCompanyParent.parentName.like("%" + parentListVO.getParentName() + "%"));
        } else if (!StringUtils.isEmpty(parentListVO.getGender())) {
            booleanBuilder.and(qCompanyParent.gender.eq(GenderType.map.get(parentListVO.getGender())));
        }
        long baseId = companyParentListVO.getBaseId() == 0 ? userId : companyParentListVO.getBaseId();
        if (admin != baseId)
            booleanBuilder.and(qCompanyParent.createUser.eq(baseId));
        List<CompanyParent> companyParents = queryFactory
                .select(qCompanyParent)
                .from(qCompanyParent)
                .where(booleanBuilder.getValue())
                .offset((companyParentListVO.getPage() - 1) * companyParentListVO.getNum())
                .limit(companyParentListVO.getNum())
                .orderBy(qCompanyParent.createTime.desc())
                .fetch();
        companyParents.stream().forEach(cp -> {
            CompanyParentListDTO companyParentListDTO = CopyUtil.copyEnty(cp, CompanyParentListDTO.class);
            companyParentListDTO.setGender(cp.getGender().name());
            companyParentListDTO.setIcon(cp.getIcon());
            companyParentListDTO.setParentName(cp.getParentName());
            companyParentListDTO.setParentPhone(cp.getParentPhone());
            companyParentListDTO.setCompanyId(cp.getCompanyId());
            relationshipService.relationshipsList(cp.getId(), 0).stream().forEach(rs -> {
                CompanyPersonal companyPersonal = companyPersonalService.RelationshipPersonalId(rs.getBindSon());
                BindRelationshipDTO bindRelationshipDTO = new BindRelationshipDTO();
                bindRelationshipDTO.setPersonalName(companyPersonal.getPersonalName());
                bindRelationshipDTO.setRelationship(rs.getRelationship().name());
                companyParentListDTO.getBindRelationship().add(bindRelationshipDTO);
            });
            companyParentListDTOS.add(companyParentListDTO);
        });

        return companyParentListDTOS;

    }
}
